#include "rtc_board.h"
#include "user_sleep.h"
#include "irq_contorl.h"
#include "user_system.h"
#include "bluetooth_app.h"

/**
 * @brief 应用层任务处理
 *
 * @param TaskId - 任务句柄
 * @param Events - 事件类型
 */
static uint16_t HardwarwProcessEvent(uint8_t TaskId, uint16_t Events);

uint8_t HalEventTask = 0;
uint32_t g_LLE_IRQLibHandlerLocation = 0;
__attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4] = {0};

#if (defined(BLE_MAC)) && (BLE_MAC == TRUE)
uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02};
#endif

#if (defined(BLE_SNV)) && (BLE_SNV == TRUE)
uint32_t Lib_Read_Flash(uint32_t AddrOffset, uint32_t SizeOut, uint32_t *pDataOut)
{
  EEPROM_READ(AddrOffset, pDataOut, SizeOut * 4);
  return 0;
}

uint32_t LibraryWriteFlash(uint32_t AddrOffset, uint32_t SizeIn, uint32_t *pDataIn)
{
  EEPROM_ERASE(AddrOffset, SizeIn * 4);
  EEPROM_WRITE(AddrOffset, pDataIn, SizeIn * 4);

  return 0;
}
#endif

uint16_t HalGetInterTempValue(void)
{
  uint16_t AdcData = 0;
  uint8_t AdcTmpSensor = 0, AdcChannel = 0, AdcConfig = 0, TKeyConfig = 0;

  TKeyConfig = R8_TKEY_CFG;
  AdcTmpSensor = R8_TEM_SENSOR;
  AdcChannel = R8_ADC_CHANNEL;
  AdcConfig = R8_ADC_CFG;
  ADC_InterTSSampInit();
  R8_ADC_CONVERT |= RB_ADC_START;
  while (R8_ADC_CONVERT & RB_ADC_START)
    ;

  AdcData = R16_ADC_DATA;
  R8_TEM_SENSOR = AdcTmpSensor;
  R8_ADC_CHANNEL = AdcChannel;
  R8_ADC_CFG = AdcConfig;
  R8_TKEY_CFG = TKeyConfig;

  return AdcData;
}

void HardwareInit(void)
{
  HalEventTask = TMOS_ProcessEventRegister(HardwarwProcessEvent);

  RtcHardwareInitialization();
  SystemSleepInit();

#if (defined BLE_CALIBRATION_ENABLE) && (BLE_CALIBRATION_ENABLE == TRUE)
  tmos_start_task(HalEventTask, HAL_REG_INIT_EVENT, MS1_TO_SYSTEM_TIME(BLE_CALIBRATION_PERIOD));
#endif
}

void BluetoothLibraryInit(void)
{
  uint8_t i = 0;
  bleConfig_t SystenConfiguration = {0};

  PRINT("[system]: power on.\r\n");
  if (tmos_memcmp(VER_LIB, VER_FILE, strlen(VER_FILE)) == FALSE)
  {
    PRINT("[system]: head file error.\r\n");
    while (1)
      ;
  }

  PRINT("[system]: firmware version number: %s.\r\n", VER_LIB);

  SysTick_Config(SysTick_LOAD_RELOAD_Msk);
  PFIC_DisableIRQ(SysTick_IRQn);

  g_LLE_IRQLibHandlerLocation = (uint32_t)LLE_IRQLibHandler;
  PFIC_SetPriority(BLEL_IRQn, 0xF0);

  tmos_memset(&SystenConfiguration, 0, sizeof(bleConfig_t));
  SystenConfiguration.MEMAddr = (uint32_t)MEM_BUF;
  SystenConfiguration.MEMLen = (uint32_t)BLE_MEMHEAP_SIZE;
  SystenConfiguration.BufMaxLen = (uint32_t)BLE_BUFF_MAX_LEN;
  SystenConfiguration.BufNumber = (uint32_t)BLE_BUFF_NUM;
  SystenConfiguration.TxNumEvent = (uint32_t)BLE_TX_NUM_EVENT;
  SystenConfiguration.TxPower = (uint32_t)BLE_TX_POWER;

#if (defined(BLE_SNV)) && (BLE_SNV == TRUE)
  if ((BLE_SNV_ADDR + BLE_SNV_BLOCK * BLE_SNV_NUM) > (0x78000 - FLASH_ROM_MAX_SIZE))
  {
    PRINT("[system]: snv config error.\r\n");
    while (1)
      ;
  }

  SystenConfiguration.SNVAddr = (uint32_t)BLE_SNV_ADDR;
  SystenConfiguration.SNVBlock = (uint32_t)BLE_SNV_BLOCK;
  SystenConfiguration.SNVNum = (uint32_t)BLE_SNV_NUM;
  SystenConfiguration.readFlashCB = Lib_Read_Flash;
  SystenConfiguration.writeFlashCB = LibraryWriteFlash;
#endif

  SystenConfiguration.ConnectNumber = (PERIPHERAL_MAX_CONNECTION & 3) | (CENTRAL_MAX_CONNECTION << 2);
  SystenConfiguration.srandCB = SYS_GetSysTickCnt;

#if (defined TEM_SAMPLE) && (TEM_SAMPLE == TRUE)
  SystenConfiguration.tsCB = HalGetInterTempValue;
#if (CLK_OSC32K)
  SystenConfiguration.rcCB = LibraryCalibrationLSI;
#endif
#endif

#if (defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
  SystenConfiguration.idleCB = SystemIntoLowPower;
#endif

#if (defined(BLE_MAC)) && (BLE_MAC == TRUE)
  for (i = 0; i < MAC_ADDR_CODING_LENGTH; i++)
  {
    SystenConfiguration.MacAddr[i] = MacAddr[5 - i];
  }
#else
  {
    uint8_t MacAddr[MAC_ADDR_CODING_LENGTH] = {0};
    GetMACAddress(MacAddr);
    for (i = 0; i < MAC_ADDR_CODING_LENGTH; i++)
    {
      SystenConfiguration.MacAddr[i] = MacAddr[i];
    }
  }
#endif

  if ((!SystenConfiguration.MEMAddr) || (SystenConfiguration.MEMLen < 4 * 1024))
  {
    while (1)
      ;
  }

  i = BLE_LibInit(&SystenConfiguration);
  if (i)
  {
    PRINT("[system]: library init error code: %x.\r\n", i);
    while (1)
      ;
  }
}

static uint16_t HardwarwProcessEvent(uint8_t TaskId, uint16_t Events)
{
  if (Events & HAL_REG_INIT_EVENT)
  {
#if (defined BLE_CALIBRATION_ENABLE) && (BLE_CALIBRATION_ENABLE == TRUE)
    uint8_t x32Kpw = 0;
#ifndef RF_8K
    BLE_RegInit();
#endif

#if (CLK_OSC32K)
    LibraryCalibrationLSI();
#elif (HAL_SLEEP)
    x32Kpw = (R8_XT32K_TUNE & 0xfc) | 0x01;
    sys_safe_access_enable();
    R8_XT32K_TUNE = x32Kpw;
    sys_safe_access_disable();
#endif
    tmos_start_task(HalEventTask, HAL_REG_INIT_EVENT, MS1_TO_SYSTEM_TIME(BLE_CALIBRATION_PERIOD));
#endif

    return Events ^ HAL_REG_INIT_EVENT;
  }

  return 0;
}

void GetLastResetStatus(void)
{
  uint8_t ResetSta = 0;

  ResetSta = SYS_GetLastResetSta() & 0x07;
  switch (ResetSta)
  {
  case 0:
    PRINT("[error]: software reset = %04X \r\n", ResetSta);
    break;

  case 1:
    PRINT("[error]: pwer-on reset RPOR = %04X \r\n", ResetSta);
    break;

  case 2:
    PRINT("[error]: watchdog timeout rese WTR = %04X \r\n", ResetSta);
    break;

  case 3:
    PRINT("[error]: external manual reset MR = %04X \r\n", ResetSta);
    break;

  case 5:
    PRINT("[error]: reset when waking up from power-down mode GRWSM = %04X \r\n", ResetSta);
    break;

  default:
    PRINT("[error]: wake-up reset LRW = %04X \r\n", ResetSta);
    break;
  }
}

__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void GPIOA_IRQHandler(void)
{
  TraversalIrqTable();
}

__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void GPIOB_IRQHandler(void)
{
  TraversalIrqTable();
}
